package com.kk.poseidon.config.spring.schema;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

import com.kk.poseidon.config.common.ProtocolConfig;

/**
* PoseidonBeanDefinitionParser.java
*
* @author chengkai
* @date  2017年5月19日 下午2:31:55
*/
public class PoseidonBeanDefinitionParser implements BeanDefinitionParser {

    private final Class<?> beanClass;

    private final boolean required;

    public PoseidonBeanDefinitionParser(Class<?> beanClass, boolean required) {
        this.beanClass = beanClass;
        this.required = required;
    }

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        return parse(element, parserContext, beanClass, required);
    }

    private BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(beanClass);
        beanDefinition.setLazyInit(false);
        String id = element.getAttribute("id");
        if ((id == null || id.length() == 0) && required) {
            String generatedBeanName = element.getAttribute("name");
            if (generatedBeanName == null || generatedBeanName.length() == 0) {
                // 如协议名称为空,则默认为poseidon
                if (ProtocolConfig.class.equals(beanClass)) {
                    generatedBeanName = "poseidon";
                } else {
                    generatedBeanName = beanClass.getName();
                }
            }
            id = generatedBeanName;
            // 避免ID重复
            int counter = 2;
            while (parserContext.getRegistry().containsBeanDefinition(generatedBeanName)) {
                id = generatedBeanName + (counter++);
            }
        }
        if (id != null && id.length() > 0) {
            parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
            beanDefinition.getPropertyValues().addPropertyValue("name", id);
        }

        Method[] methods = beanClass.getMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            if (methodName.length() > 3 && methodName.startsWith("set") && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 1) {
                String property = methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
                String value = element.getAttribute(property);
                beanDefinition.getPropertyValues().addPropertyValue(property, value);
            }
        }

        parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
        return beanDefinition;
    }

}
